#pragma once
#include<iostream>
#include<vector>
#include<pthread.h>
#include<queue>

using namespace std;

class ThreadPool
{
public:
    ThreadPool(int _threadCount=5)
    :stopFlag(false)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<_threadCount;i++){
            pthread_create(&_threads[i],nullptr,ThreadFunction,this);
        }
    }
    void addTask(void(*newTask)(void*),void* args)
    {
        pthread_mutex_lock(&_mutex);
        _taskQueue.push(make_pair(newTask,args));
        pthread_cond_signal(&_cond);
        pthread_mutex_unlock(&_mutex);
    }
    void stop()
    {
        stopFlag=true;
        pthread_cond_broadcast(&_cond);
        for(int i=0;i<_threads.size();i++){
            pthread_join(_threads[i],nullptr);
        }
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    ~ThreadPool()
    {
        stop();
    }
private:
    static void* ThreadFunction(void* args)
    {
        ThreadPool* poolptr=static_cast<ThreadPool*>(args);
        while(!poolptr->stopFlag)
        {
            while(poolptr->_taskQueue.empty() && !(poolptr->stopFlag)){
                pthread_cond_wait(&(poolptr->_cond),&(poolptr->_mutex));
            }
            if(poolptr->stopFlag){
                break;
            }
            void (*task)(void*)=poolptr->_taskQueue.front().first;
            void* taskArgs=poolptr->_taskQueue.front().second;
            task(taskArgs);
        }
        return nullptr;
    }
private:
    bool stopFlag=false;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    vector<pthread_t> _threads;
    queue<pair<void (*)(void*),void*>>_taskQueue;
};
// class ThreadPool
// {
// public:
//     ThreadPool(int _threadCount=5)
//     :stopFlag(false)
//     {
//         _threads.resize(_threadCount);
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//         for(int i=0;i<_threadCount;i++){
//             pthread_create(&_threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     void addTask(void(*newTask)(void*),void* args)
//     {
//         pthread_mutex_lock(&_mutex);
//         _taskQueue.push(make_pair(newTask,args));
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     void stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&_cond);
//         for(int i=0;i<_threads.size();i++){
//             pthread_join(_threads[i],nullptr);
//         }
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }
//     ~ThreadPool(){
//         stop();
//     }
// private:
//     static void* ThreadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(!poolptr->stopFlag)
//         {
//             pthread_mutex_lock(&(poolptr->_mutex));
//             while(poolptr->_taskQueue.empty() && !poolptr->stopFlag){
//                 pthread_cond_wait(&(poolptr->_cond),&(poolptr->_mutex));
//             }
//             if(poolptr->stopFlag){
//                 break;
//             }
//             void (*task)(void*)=poolptr->_taskQueue.front().first;
//             void* taskArgs=poolptr->_taskQueue.front().second;
//             poolptr->_taskQueue.pop();
//             pthread_mutex_unlock(&(poolptr->_mutex));
//             task(taskArgs);
//         }
//         return nullptr;
//     }
// private:
//     vector<pthread_t> _threads;
//     queue<pair<void(*)(void*),void*>> _taskQueue;
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
//     bool stopFlag;
// };
// class ThreadPool
// {
// public:
//     ThreadPool(int _thread_num=5)
//     :stopFlag(false)
//     {
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//         for(int i=0;i<_thread_num;i++){
//             pthread_create(&_threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     void addTask(void(*newTask)(void*),void* args)
//     {
//         pthread_mutex_lock(&_mutex);
//         _taskQueue.push(make_pair(newTask,args));
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     void stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&_cond);
//         for(int i=0;i<_threads.size();i++){
//             pthread_join(_threads[i],nullptr);
//         }
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }
//     ~ThreadPool()
//     {
//         stop();
//     }
// private:
//     static void* ThreadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(!poolptr->stopFlag)
//         {
//             pthread_mutex_lock(&(poolptr->_mutex));
//             while(poolptr->_taskQueue.empty() && !poolptr->stopFlag){
//                 pthread_cond_wait(&(poolptr->_cond),&(poolptr->_mutex));
//             }
//             if(poolptr->stopFlag){
//                 break;
//             }
//             void(*task)(void*)=poolptr->_taskQueue.front().first;
//             void* taskArgs=poolptr->_taskQueue.front().second;
//             task(taskArgs);
//         }
//         return nullptr;
//     }
// private:
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
//     vector<pthread_t> _threads;
//     queue<pair<void (*)(void*),void*>>_taskQueue;
//     bool stopFlag;
// };
// class ThreadPool
// {
// public:
//     ThreadPool(int _threadCount=5)
//     :stopFlag(false)
//     {
//         //线程池的初始化工作就是创建好线程，并且对他们进行锁的分配
//         _threads.resize(_threadCount);
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//         for(int i=0;i<_threadCount;i++){
//             pthread_create(&_threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     void addTask(void(*newTask)(void*),void* args)
//     {
//         pthread_mutex_lock(&_mutex);
//         _taskQueue.push(make_pair(newTask,args));
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     void stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&_cond);
//         for(int i=0;i<_threads.size();i++){
//             pthread_join(_threads[i],nullptr);
//         }
//         pthread_cond_signal(&_cond);
//         pthread_mutex_unlock(&_mutex);
//     }
//     ~ThreadPool(){
//         stop();
//     }
// private:
//     static void* ThreadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(!poolptr->stopFlag)
//         {
//             pthread_mutex_lock(&poolptr->_mutex);
//             while(poolptr->_taskQueue.empty() && !poolptr->stopFlag){
//                 pthread_cond_wait(&(poolptr->_cond),&(poolptr->_mutex));
//             }
//             if(poolptr->stopFlag){
//                 break;
//             }
//             void (*task)(void*)=poolptr->_taskQueue.front().first;
//             void* taskArgs=poolptr->_taskQueue.front().second;
//             task(taskArgs);
//         }
//         return nullptr;
//     }
// private:
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
//     vector<pthread_t> _threads;
//     //声明这里只需要填写类型就好了
//     queue<pair<void (*)(void*),void*>> _taskQueue;
//     bool stopFlag;
// };